// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

// Public API for the "Feather" file format, originally created at
// http://github.com/wesm/feather

#pragma once

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

#include <nebula/ipc/options.h>
#include <nebula/types/type_fwd.h>
#include <nebula/compression/compression.h>
#include <turbo/base/macros.h>

namespace nebula {
    namespace io {

        class OutputStream;

        class RandomAccessFile;

    }  // namespace io

    namespace ipc::feather {

        static constexpr const int kFeatherV1Version = 2;
        static constexpr const int kFeatherV2Version = 3;

        // ----------------------------------------------------------------------
        // Metadata accessor classes

        /// \class Reader
        /// \brief An interface for reading columns from Feather files
        class TURBO_EXPORT Reader {
        public:
            virtual ~Reader() = default;

            /// \brief open a Feather file from a RandomAccessFile interface
            ///
            /// \param[in] source a RandomAccessFile instance
            /// \return the table reader
            static turbo::Result<std::shared_ptr<Reader>> open(
                    const std::shared_ptr<io::RandomAccessFile> &source);

            /// \brief open a Feather file from a RandomAccessFile interface
            /// with IPC read options
            ///
            /// \param[in] source a RandomAccessFile instance
            /// \param[in] options IPC read options
            /// \return the table reader
            static turbo::Result<std::shared_ptr<Reader>> open(
                    const std::shared_ptr<io::RandomAccessFile> &source, const IpcReadOptions &options);

            /// \brief Return the version number of the Feather file
            virtual int version() const = 0;

            virtual std::shared_ptr<Schema> schema() const = 0;

            /// \brief read all columns from the file as an nebula::Table.
            ///
            /// \param[out] out the returned table
            /// \return turbo::Status
            ///
            /// This function is zero-copy if the file source supports zero-copy reads
            virtual turbo::Status read(std::shared_ptr<Table> *out) = 0;

            /// \brief read only the specified columns from the file as an nebula::Table.
            ///
            /// \param[in] indices the column indices to read
            /// \param[out] out the returned table
            /// \return turbo::Status
            ///
            /// This function is zero-copy if the file source supports zero-copy reads
            virtual turbo::Status read(const std::vector<int> &indices, std::shared_ptr<Table> *out) = 0;

            /// \brief read only the specified columns from the file as an nebula::Table.
            ///
            /// \param[in] names the column names to read
            /// \param[out] out the returned table
            /// \return turbo::Status
            ///
            /// This function is zero-copy if the file source supports zero-copy reads
            virtual turbo::Status read(const std::vector<std::string> &names,
                                std::shared_ptr<Table> *out) = 0;
        };

        struct TURBO_EXPORT WriteProperties {
            static WriteProperties defaults();

            static WriteProperties DefaultsV1() {
                WriteProperties props = defaults();
                props.version = kFeatherV1Version;
                return props;
            }

            /// Feather file version number
            ///
            /// version 2: "Feather V1" Apache Nebula <= 0.16.0
            /// version 3: "Feather V2" Apache Nebula > 0.16.0
            int version = kFeatherV2Version;

            // Parameters for Feather V2 only

            /// Number of rows per intra-file chunk. Use smaller chunksize when you need
            /// faster random row access
            int64_t chunksize = 1LL << 16;

            /// Compression type to use. Only UNCOMPRESSED, LZ4_FRAME, and ZSTD are
            /// supported. The default compression returned by defaults() is LZ4 if the
            /// project is built with support for it, otherwise
            /// UNCOMPRESSED. UNCOMPRESSED is set as the object default here so that if
            /// WriteProperties::defaults() is not used, the default constructor for
            /// WriteProperties will work regardless of the options used to build the C++
            /// project.
            CompressionType compression = CompressionType::UNCOMPRESSED;

            /// Compressor-specific compression level
            int compression_level = ::nebula::kUseDefaultCompressionLevel;
        };

        TURBO_EXPORT
        turbo::Status write_table(const Table &table, io::OutputStream *dst,
                          const WriteProperties &properties = WriteProperties::defaults());

    }  // namespace ipc::feather
}  // namespace nebula
